package qr.server.admin;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;
import java.util.Map;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import qr.core.Game;
import qr.server.managers.TransactionGateway;

@SuppressWarnings("serial")
public class HomeScreen extends ApplicationScreen {

	private DefaultListModel gamesModel = new DefaultListModel();
	
	private JLabel status;
	private JList games;
	
	private JPanel actions;
	
	private JButton createGame;
	private JButton startGame;
	private JButton editGame;
	private JButton deleteGame;
	
	public HomeScreen(ApplicationWindow parent) {
		super(parent);
		
		this.setLayout(new BorderLayout());
		
		// Create panels		
		//Sets up Status label.
		this.status = new JLabel();
		updateStatusLabel();
		
		//Sets up Game Model
		this.games = new JList();
		List<Game> gms = TransactionGateway.getInstance().getAllGames();
		for(Game g : gms) {
			gamesModel.addElement(g);
		}
		this.games.setModel(gamesModel);
		this.actions = new JPanel(new FlowLayout());
		
		// Create components
		this.createGame = new JButton("Create Game");
		this.startGame = new JButton("Start Game"); // "Stop Game"
		this.startGame.setEnabled(false);
		this.editGame = new JButton("Edit Game");
		this.editGame.setEnabled(false);
		this.deleteGame = new JButton("Delete Game");
		this.deleteGame.setEnabled(false);

		// Place components
		this.actions.add(this.createGame);
		this.actions.add(this.startGame);
		this.actions.add(this.editGame);
		this.actions.add(this.deleteGame);
		
		this.add(this.status, BorderLayout.NORTH);
		this.add(new JScrollPane(games), BorderLayout.CENTER);
		this.add(this.actions, BorderLayout.SOUTH);

		this.games.addListSelectionListener(new ListSelectionListener() {
			@Override
			public void valueChanged(ListSelectionEvent e) {
				Game g = (Game) games.getSelectedValue();
				startGame.setEnabled(g != null ? true : false);
				editGame.setEnabled(g != null ? true : false);
				deleteGame.setEnabled(g != null ? true : false);
				startGame.setText(g == null || !g.isRunning() ? "Start Game" : "Stop Game");
			}
			
			
		});
		
		this.games.addMouseListener(new MouseAdapter() {
		    public void mouseClicked(MouseEvent evt) {
		        if (evt.getClickCount() == 2) {
		            Game g = (Game) games.getSelectedValue();
		    		switchTo("CreateGameScreen", new Object[]{g});
		        }
		    }
		});
		
		this.createGame.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				createGameClicked(e);
			}
		});
		this.startGame.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				startGameClicked(e);
			}
		});
		this.editGame.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				editGameClicked(e);
			}
		});
		this.deleteGame.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				deleteGameClicked(e);
			}
		});
		
	}

	/**
	 * Handler for click event of the createGame button.
	 * 
	 * @param e Event object
	 */
	private void createGameClicked(ActionEvent e) {
		switchTo("CreateGameScreen", new Object[]{new Game()});
	}
	
	/**
	 * Handler for click event of the startGame button.
	 * 
	 * @param e Event object
	 */
	private void startGameClicked(ActionEvent e) {
		Game g = (Game) games.getSelectedValue();
		TransactionGateway db = TransactionGateway.getInstance();
		
		db.startTransaction();
		if(g.isRunning()) {
			g.stopGame();
		} else {
			if(db.hasStartedGame()) {
				Game startedGame = db.getCurrentGame();
				if(JOptionPane.showConfirmDialog(this, "There is already a game running: "
						+ startedGame.getGameName() + ".\nDo you wish to stop that game and start this one?",
						"Starting Game", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
					startedGame.stopGame();
					g.startGame();
					startGame.setText("Stop Game");
				}
			} else {
				g.startGame();
				startGame.setText("Stop Game");
			}
		}
		db.endTransaction();
		updateStatusLabel();
	}
	
	/**
	 * Handler for click event of the editGame button.
	 * 
	 * @param e Event object
	 */
	private void editGameClicked(ActionEvent e) {
		Game g = (Game) games.getSelectedValue();
		switchTo("CreateGameScreen", new Object[]{g});
	}
	
	/**
	 * Handler for click event of the deleteGame button.
	 * 
	 * @param e Event object
	 */
	private void deleteGameClicked(ActionEvent e) {
		Game g = (Game) games.getSelectedValue();
		if(g != null && JOptionPane.showConfirmDialog(this, "Delete selected game? This cannot be undone.", "Delete game?", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
			TransactionGateway.getInstance().deleteGame(g.getId());
			gamesModel.remove(games.getSelectedIndex());
			updateStatusLabel();
		}
	}
	
	private void updateStatusLabel(){
		TransactionGateway db = TransactionGateway.getInstance();
		if(db.hasStartedGame()){
			this.status.setText("Server Status: " + 
					db.getCurrentGame().getGameName() + " is running!");
		} else {
			this.status.setText("Server Status: not running.");
		}
	}
}
